/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package src.view.deposit;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.primefaces.context.RequestContext;
import org.primefaces.event.CloseEvent;
import src.domain.customer.Customer;
import src.domain.deposit.Bilyet;
import src.domain.deposit.Deproduct;
import src.domain.gl.Glaccnt;
import src.domain.saving.Saving;
import src.domain.security.Users;
import src.services.customer.CustomerModel;
import src.services.deposit.BilyetModel;
import src.services.deposit.DeproductModel;
import src.services.gl.GlaccntConverter;
import src.services.gl.GlaccntModel;
import src.services.gl.TaxModel;
import src.services.saving.SavingModel;
import src.util.Constanta;
import src.util.Messager;
import src.view.security.LoginBean;

/**
 *
 * @author Yusup Jauhari Shandi <in.visi>
 */

@ManagedBean
@SessionScoped
public class BilyetBean implements Serializable{
    private boolean editMode = false,  insertionMode = true, authorized=false;
    private Bilyet bilyet;
    private DeproductModel prodHelper;
    private BilyetModel bilHelper;

    private List<SelectItem> avblProd, avblDisb, avblStatus;
    private List<Glaccnt> avblGL;
    private Glaccnt depositGlaccnt;
    private String accntDest, bilyetParentNo, accntOwner, depSavaccnt, depSavaccntOwner;
    private Integer branchId, bankId;
    private BigDecimal taxRate = BigDecimal.ZERO;
    private BigDecimal percentDivisor = new BigDecimal(100);
    private BigDecimal saldo = new BigDecimal(0);
    private Users user;
    private boolean showLookup=false;
    
    
    public BilyetBean() {
        ambilUser();
        this.bilHelper = new BilyetModel();
        this.prodHelper = new DeproductModel();  
        this.avblDisb = Constanta.getDepDisb();
        this.avblStatus = Constanta.getBilyetStatus();
        this.avblGL = GlaccntConverter.glaccountDB;
        newData();
        editMode = false;  
        authorized=false;
    }

    private void ambilUser() {
        FacesContext context = FacesContext.getCurrentInstance();
        LoginBean logBean = (LoginBean) context.getApplication().evaluateExpressionGet(context, "#{loginBean}", LoginBean.class);
        this.user = logBean.getSelectedUser();
    }

    public boolean isShowLookup() {
        return showLookup;
    }

    public void setShowLookup(boolean showLookup) {
        this.showLookup = showLookup;
    }
       
    private boolean cekConfig() {
        boolean complete=true;
        this.branchId = user.getBranch().getBranchId();
        this.bankId = user.getSavBankId();
        
        if (this.branchId==null) complete=false;
        if(complete==false) Messager.showWarning("unconfig");
        return complete;
    }
        
    public Bilyet getBilyet() {
        return bilyet;
    }

    public void setBilyet(Bilyet bilyet) {
        this.bilyet = bilyet;
    }
    
    public boolean isEditMode() {
        return editMode;
    }

    public boolean isAuthorized() {
        return authorized;
    }
    
    public void setEditMode(boolean editMode) {
        this.editMode = editMode;
    }

    public String getAccntDest() {
        return accntDest;
    }

    public void setAccntDest(String accntDest) {
        this.accntDest = accntDest;
    }

    public String getBilyetParentNo() {
        return bilyetParentNo;
    }

    public void setBilyetParentNo(String bilyetParentNo) {
        this.bilyetParentNo = bilyetParentNo;
    }

    public String getAccntOwner() {
        return accntOwner;
    }

    public void setAccntOwner(String accntOwner) {
        this.accntOwner = accntOwner;
    }

    public String getDepSavaccnt() {
        return depSavaccnt;
    }

    public void setDepSavaccnt(String depSavaccnt) {
        this.depSavaccnt = depSavaccnt;
    }

    public String getDepSavaccntOwner() {
        return depSavaccntOwner;
    }

    public void setDepSavaccntOwner(String depSavaccntOwner) {
        this.depSavaccntOwner = depSavaccntOwner;
    }
    
    public List<SelectItem> getAvblDisb() {
        return avblDisb;
    }

    public List<SelectItem> getAvblProd() {
        return avblProd;
    }

    public List<SelectItem> getAvblStatus() {
        return avblStatus;
    }

    public List<Glaccnt> getAvblGL() {
        return avblGL;
    }

    public Glaccnt getDepositGlaccnt() {
        return depositGlaccnt;
    }

    public void setDepositGlaccnt(Glaccnt depositGlaccnt) {
        this.depositGlaccnt = depositGlaccnt;
    }
        
    public void initForm(){
        this.avblProd = this.prodHelper.listAll();
        this.avblGL = GlaccntConverter.glaccountDB;
        this.editMode = true;
        this.authorized = true;
        showLookup=false;
        accntDest=null;
        bilyetParentNo=null;
        accntOwner=null;
        depSavaccnt=null;
        depSavaccntOwner=null;
        taxRate = BigDecimal.ZERO;
        saldo = BigDecimal.ZERO;
    }
    
    public final void newData(){
        initForm();
        cekConfig();
        if (bilyet!=null) bilyet = null;
        bilyet = new Bilyet();
        this.bilyet.setBranchId(branchId);
        this.bilyet.setBankId(bankId);
        this.depositGlaccnt = new Glaccnt();//Model().getById(bilyet.getDepositGlaccntId());
        insertionMode = true;
    }
    
    public void getBilyetCustomer(String cif) {
        boolean found = false;
        if ("null".equals(cif)) cif = bilyet.getCustomer().getCif();
            
        if (cif!=null ) {
            Customer customer = new CustomerModel().getByCif(cif);
            if (customer==null) {
                bilyet.setCustomer(new Customer());
                Messager.showWarning("customerNotFound");
            
            }else {
                found=true;
                bilyet.setCustomer(customer);
            }
        }
        
        RequestContext.getCurrentInstance().addCallbackParam("success", found); 
    }
        
     public void getSavingDest(String norek) {
         boolean found = false;
        if ("null".equals(norek)) norek = accntDest;
        
        if (norek!=null ) {
            
            SavingModel helper = new SavingModel();
            Saving saving = null;
            if (norek!=null) {
                saving = helper.getByAccount(norek);
                if (saving !=null ) {
                    found=true;
                    this.accntOwner = saving.getCustomer().getCustomerName();
                    this.accntDest = saving.getAccountNo();
                    this.bilyet.setSavaccntId(saving.getSavaccntId());
                }
            } 
            if (saving == null) {
                this.accntDest = null;
                this.accntOwner = null;
                this.bilyet.setSavaccntId(null);
                Messager.showWarning("accntNotFound");
            }
        }
        RequestContext.getCurrentInstance().addCallbackParam("success", found); 
    }
    
    public void getSavingDep(String norek) {
         boolean found = false;
        if ("null".equals(norek)) norek = depSavaccnt;
        
        if (norek!=null ) {
            
            SavingModel helper = new SavingModel();
            Saving saving = null;
            if (norek!=null) {
                saving = helper.getByAccount(norek);
                if (saving !=null ) {
                    found=true;
                    this.depSavaccntOwner = saving.getCustomer().getCustomerName();
                    this.depSavaccnt = saving.getAccountNo();
                    this.saldo = saving.getBalance();
                    this.bilyet.setDepositSavaccntId(saving.getSavaccntId());
                    
                    if(bilyet.getPrincipleAmount().compareTo(saldo) > 0) {
                        Messager.showWarning("balanceKurang");
                    }
                }
            } 
            if (saving == null) {
                this.depSavaccnt = null;
                this.depSavaccntOwner = null;
                this.saldo = new BigDecimal(0);
                this.bilyet.setDepositSavaccntId(null);
                Messager.showWarning("accntNotFound");
            }
        }
        RequestContext.getCurrentInstance().addCallbackParam("success", found); 
    }
   
    public void getParentBiltetNo(String norek) {
        boolean found = false;
        if ("null".equals(norek)) norek = bilyetParentNo;
        
        BilyetModel helper = new BilyetModel();
        Bilyet bilparent = null;
        if (norek!=null ) {
            bilparent = helper.getByNo(norek);
            if (bilparent !=null ) {
                found=true;
                this.bilyetParentNo = bilparent.getBilyetNo();
                this.bilyet.setParentBilyetId(bilparent.getBilyetId());
            }
        } 
        if (bilparent == null) {
            this.bilyetParentNo = null;
            this.bilyet.setParentBilyetId(null);
            Messager.showWarning("billyetNotFound");
        }        
        RequestContext.getCurrentInstance().addCallbackParam("success", found); 
    }
    
    public void calcInterestAmount() {  
        BigDecimal amount = BigDecimal.ZERO;
        if (bilyet.getInterestRate() !=null && bilyet.getPrincipleAmount() != null) {
            BigDecimal intRate = bilyet.getInterestRate().divide(percentDivisor,2, RoundingMode.HALF_UP);
            amount = bilyet.getPrincipleAmount().multiply(intRate);
        }   
        bilyet.setInterestAmount(amount);
    }  
        
    public void calcTaxAmount() {  
        BigDecimal taxAmount = BigDecimal.ZERO;
        if (bilyet.getPrincipleAmount() !=null && bilyet.getInterestAmount() != null) {
            BigDecimal period = BigDecimal.valueOf(bilyet.getDeproduct().getNumOfPeriod())
                    .divide(BigDecimal.valueOf(30), 0, RoundingMode.UP);
            
            BigDecimal intmonth = bilyet.getInterestAmount().divide(period, 0, RoundingMode.CEILING);
            
            if (intmonth.compareTo(Constanta.MAX_INTEREST_TAXED) > 0) 
               taxAmount = bilyet.getInterestAmount().multiply(taxRate);
        }    
        bilyet.setTaxAmount(taxAmount);
    }  
    
    public void calculateAmount() {  
        calcInterestAmount();
        calcTaxAmount();
    }  
    
    public void cekBilyeNumber() {  
        String bilNO = bilyet.getBilyetNo();
        if (bilNO!=null) {
            boolean productExist =  bilHelper.isNoBilyetExist(bilNO, bilyet.getBilyetId());
            if (productExist==true) {
                Messager.showError("bilyetIsExist");
            }
        }
    }    
        
    public void handleProdChange() {  
        DeproductModel helper = new DeproductModel();
        Deproduct produk= new Deproduct();
        Integer id = bilyet.getDeproduct().getDeproductId();
        if (id != null) {
            bilyet.setDepositGlaccntId(produk.getDepGlaccountId());
            produk = helper.getById(id);
            taxRate = new TaxModel().getById(produk.getTaxId()).getTaxRate().divide(percentDivisor, 2, RoundingMode.HALF_DOWN);
            
            depositGlaccnt = new GlaccntModel().getById(produk.getDepGlaccountId());
            calculateAmount();
        }
        bilyet.setDeproduct(produk);
    }  
    
    public void openData(){
        initForm();
        insertionMode = false;
    }
    
    public void trySave() {
        boolean productExist;
        String bilNO = bilyet.getBilyetNo();
        productExist =  bilHelper.isNoBilyetExist(bilNO, bilyet.getBilyetId());
        if (productExist==true) {
            Messager.showError("bilyetIsExist");
        }
                
        if (productExist==false) 
            productExist = !cekConfig();
                
        if( bilyet.getDepositSavaccntId() != null && bilyet.getPrincipleAmount().compareTo(saldo) > 0) {
            productExist = true;
            Messager.showWarning("balanceKurang");
        }
        
        if (productExist==false) save();
    }
    
    private void validateLimit() {
        this.authorized = true;
        
        Integer authorizedId = bilHelper.authorized(bilyet.getBilyetId());
        
        bilyet.setUserId(user.getUserId());
        bilyet.setDepositGlaccntId(depositGlaccnt.getGlaccntId());
        bilyet.setAuthorizedUid(authorizedId);
        
        //belum diotorisasi, cek validasi
        if (authorizedId == null) {
            
            BigDecimal ddAmount = bilyet.getPrincipleAmount();
            BigDecimal ddAmountAlowed = user.getUgroup().getDepMaxDeposit();
        
            if(ddAmount.compareTo(ddAmountAlowed) >= 0) this.authorized=false;
            
            //jika dlm rage limit, authorizedId = userId
            else bilyet.setAuthorizedUid(user.getUserId());
        }
        
        //men-triger history and balance
        //bilyet.setPosted(authorized);
    }
    
    private void save(){
        
        validateLimit();
                
        boolean success = bilHelper.saveData(bilyet);
        //this.editMode = (!success || !authorized);
        this.editMode = (!success);
        Messager.showSaveUpdateStatus(success);     
        
        if (!authorized && success)
            Messager.showWarning("unauthorized");    
        
        //ngahaja. biar inputBox bisa ngisi klo eror
        if (!success) authorized = true;
        else {
            
            //kalo sukses & athorized....
            if (authorized) authorized = false;
        }    
        
        // re-insert
        if (!success && insertionMode) bilyet.setBilyetId(null);
        else insertionMode = false;
        
        RequestContext.getCurrentInstance().addCallbackParam("success", success); 
    }
    
    public void handleCloseLookup(CloseEvent event) {
        this.showLookup=false;
    }

    public BigDecimal getSaldo() {
        return saldo;
    }
   
}
